/**
  **********************************************************************************************************************
  * @file    cot_os.c
  * @brief   该文件提供查询协作式多任务系统功能
  * @author  const_zpc  any question please send mail to const_zpc@163.com
  * @version V1.2.0
  * @date    2025-5-11
  *
  * @details  功能详细说明：
  *           + 任务调度初始化
  *           + 任务调度功能启动
  *           + 该任务调度并非抢占式
  *
  **********************************************************************************************************************
  * 源码路径：https://gitee.com/cot_package/cot_os.git 具体问题及建议可在该网址填写 Issue
  *
  * 使用方式:
  *    1. 使用前初始化函数 cotOs_Init
  *    2. 通过 cotOs_CreatTaskWithStack 或 cotOs_CreatTask 添加任务函数
  *    3. 主函数调用 cotOs_Start 启动任务调度, 存在任务函数时不会退出
  *    4. 使用 cotOs_Wait 切换到下一个任务执行
  *
  **********************************************************************************************************************
  */

/* Includes ----------------------------------------------------------------------------------------------------------*/

#include <stdbool.h>
#include "cot_os_config.h"
#include <setjmp.h>
#include "cot_os.h"

/* Private typedef ---------------------------------------------------------------------------------------------------*/

#define COT_OS_MAX_TASK (COT_OS_MAX_UNIQUE_TASK + COT_OS_MAX_SHARED_TASK)

#if (COT_OS_MAX_TASK > 32)
#error "task max num can't over 32"
#endif

#if (COT_OS_MAX_TASK == 0)
#error "task min num can't less than 1"
#endif

/**
  * @brief      任务栈类型
  * 
  */
typedef enum
{
    COT_OS_UNIQUE_STACK = 0,            /*!(0) 独立栈 */
    COT_OS_SHARED_STACK                 /*!(1) 共享栈 */
} CotOSStackType_e;

typedef struct stTCB
{
    char szName[COT_OS_TASK_NAME_LENGTH];
    uint16_t pid;
    uint8_t state;
    uint8_t joinWaitCnt;
    CotOSCondition_t cond;
    size_t stackTop;
    size_t stackSize;
    CotOSStackType_e eStackType;
    uint32_t nextRunTime;
    int param;
    jmp_buf env;
    cotOsTask_f pfnOsTaskEnter;
    CotOSCondition_t *pCondition;
#if COT_OS_MAX_SHARED_TASK > 0
    uint8_t *pBakStack;
    size_t stackUsed;
#endif
    struct stTCB *pNext;
} TCB_t;

/**
  * @brief 中断任务信息结构体定义
  */
typedef struct stuOsInfo
{
    cotOsGetSysTime_f pfnGetTimerMs;                /*!< 获取毫秒级别的时间回调函数 */

    TCB_t *pCurTCB;

    TCB_t *pTCBList;
#if COT_OS_MAX_SHARED_TASK > 0
    uint32_t tcbStackMask;
#endif
    uint32_t tcbMask;

    jmp_buf env;

    jmp_buf envResume;

    uint16_t pidCount;

    // 下面定义的回调函数是防止编译器优化成内联函数使用，破坏压栈顺序导致无法正常运行
    void (*pfnRunTask)(uint32_t); 
    
    size_t (*pfnGetStackTop)(void);

    size_t (*pfnCalculateStackUsage)(TCB_t *);
} OsInfo_t;

/* Private define ----------------------------------------------------------------------------------------------------*/

#define COMMON_TASK_INTI                0
#define COMMON_TASK_RUN                 1

#define MAIN_TASK_INTI                  0
#define MAIN_TASK_EXIT                  1
#define MAIN_TASK_JUMP_SHARED_TASK      2
#define MAIN_TASK_START_TASK            3

#define TASK_STATUS_INIT                0
#define TASK_STATUS_READY               1
#define TASK_STATUS_RUNNING             2
#define TASK_STATUS_SUSPEND             3
#define TASK_STATUS_DELETED             4

#define TCB_MAGIC                       0xDEADBEEF

/* Private macro -----------------------------------------------------------------------------------------------------*/
/* Private variables -------------------------------------------------------------------------------------------------*/

static OsInfo_t sg_OsInfo;
static TCB_t sg_TCB[COT_OS_MAX_TASK];
#if COT_OS_MAX_SHARED_TASK > 0
static uint8_t sg_shareTCBStack[COT_OS_MAX_SHARED_TASK][COT_OS_MAX_SHARED_BAK_STACK_SIZE];
#endif

/* Private function prototypes ---------------------------------------------------------------------------------------*/
static void MaxStrpy(char *out, const char *in, size_t maxLength);
static void TcbMemcpy(uint8_t *pdest, uint8_t *psrc, size_t length);
static size_t GetStackTop(void);
static size_t CalculateStackUsage(TCB_t *pTCB);
static void BackupSharedStack(TCB_t *pTCB);
static TCB_t *CreatTCB(OsInfo_t *pObj);
static void DestroyTCB(OsInfo_t *pObj, TCB_t *pCurTCB);
#if COT_OS_MAX_SHARED_TASK > 0
static uint8_t *CreatTCBStack(OsInfo_t *pObj);
static void DestroyTCBStack(OsInfo_t *pObj, TCB_t *pCurTCB);
#endif
static void AddToTCBTaskList(OsInfo_t *pObj, TCB_t *pNewTCB);
static void DeleteFromTCBTaskList(OsInfo_t *pObj, TCB_t *pCurTCB);
static uint8_t GetTaskNum(OsInfo_t *pObj);
static void DestoryTask(OsInfo_t *pObj, TCB_t *pCurTCB);
static void RunTask(uint32_t check);
#if COT_OS_MAX_SHARED_TASK > 0
static void StartSharedTask(void);
static void UseBuffer(volatile char* buf);
#endif
static void JumpNextTask(OsInfo_t *pObj);

/* Private function --------------------------------------------------------------------------------------------------*/
static void MaxStrpy(char *out, const char *in, size_t maxLength)
{
    while (*in != '\0' && maxLength > 1)
    {
        *out = *in;
        out++;
        in++;
        maxLength--;
    }

    *out = '\0';
}

static void TcbMemcpy(uint8_t *pdest, uint8_t *psrc, size_t length)
{
    volatile uint8_t *d = (volatile uint8_t *)pdest;
    volatile uint8_t *s = (volatile uint8_t *)psrc;

    while (length--) 
    {
        *d++ = *s++;
    }
}

static size_t GetStackTop(void)
{
    volatile char stack_anchor;
    size_t stack_top = (size_t)&stack_anchor + sizeof(stack_anchor);
    return (stack_top + 15) & ~15UL; // 16字节对齐
}

#if COT_OS_MAX_SHARED_TASK > 0
static size_t CalculateStackUsage(TCB_t *pTCB)
{
    volatile char anchor;
    size_t current_sp = (size_t)&anchor;
    size_t stack_used = pTCB->stackTop - current_sp + 32; // 保留32字节安全区
    return (stack_used + 15) & ~15UL; // 16字节对齐
}

static void BackupSharedStack(TCB_t *pTCB) 
{
    pTCB->stackUsed = sg_OsInfo.pfnCalculateStackUsage(pTCB);
    // 程序卡在这则说明有该共享栈任务使用的备份栈超过了设定值，说明有以下原因：
    // 1. COT_OS_MAX_SHARED_BAK_STACK_SIZE 定义的值过小
    // 2. 该共享栈任务定义了很多变量或者有个大内存变量
    // 3. 不按规定在嵌套函数中使用了`cotOs_Wait`或`cotOs_ConditionWait`函数
    while (pTCB->stackUsed > COT_OS_MAX_SHARED_BAK_STACK_SIZE);
    TcbMemcpy(pTCB->pBakStack, (uint8_t*)(pTCB->stackTop - pTCB->stackUsed), pTCB->stackUsed);
}

static void RestoreSharedStack(TCB_t *pTCB) 
{
    // 保留256字节安全区
    while (sg_OsInfo.pfnGetStackTop() - 256 < pTCB->stackTop); // 卡在这里说明 COT_OS_SHARED_TASK_JMP_STACK_SIZE 定义的值过小

    TcbMemcpy((uint8_t*)(pTCB->stackTop - pTCB->stackUsed), pTCB->pBakStack, pTCB->stackUsed);
}
#endif

static TCB_t *CreatTCB(OsInfo_t *pObj)
{
    for (int i = 0; i < COT_OS_MAX_TASK; i++)
    {
        if (!((pObj->tcbMask >> i) & 0x01))
        {
            pObj->tcbMask |= (0x1 << i);
            return &sg_TCB[i];
        }
    }

    return NULL;
}

static void DestroyTCB(OsInfo_t *pObj, TCB_t *pCurTCB)
{
    for (int i = 0; i < COT_OS_MAX_TASK; i++)
    {
        if (&sg_TCB[i] == pCurTCB)
        {
            pObj->tcbMask &= ~(0x1 << i);
            break;
        }
    }
}

#if COT_OS_MAX_SHARED_TASK > 0
static uint8_t *CreatTCBStack(OsInfo_t *pObj)
{
    for (int i = 0; i < COT_OS_MAX_SHARED_TASK; i++)
    {
        if (!((pObj->tcbStackMask >> i) & 0x01))
        {
            pObj->tcbStackMask |= (0x1 << i);
            return sg_shareTCBStack[i];
        }
    }

    return NULL;
}

static void DestroyTCBStack(OsInfo_t *pObj, TCB_t *pCurTCB)
{
    for (int i = 0; i < COT_OS_MAX_SHARED_TASK; i++)
    {
        if (sg_shareTCBStack[i] == pCurTCB->pBakStack)
        {
            pObj->tcbStackMask &= ~(0x1 << i);
            break;
        }
    }
}
#endif

static void AddToTCBTaskList(OsInfo_t *pObj, TCB_t *pNewTCB)
{
    if (pObj->pTCBList == NULL)
    {
        pObj->pTCBList = pNewTCB;
        pObj->pTCBList->pNext = pObj->pTCBList;
    }
    else
    {
        TCB_t *pTCB = pObj->pTCBList;

        while (pTCB->pNext != NULL && pTCB->pNext != pObj->pTCBList)
        {
            pTCB = pTCB->pNext;
        }

        pNewTCB->pNext = pTCB->pNext;
        pTCB->pNext = pNewTCB;
    }
}

static void DeleteFromTCBTaskList(OsInfo_t *pObj, TCB_t *pCurTCB)
{
    TCB_t *pTCB = pObj->pTCBList;

    if (pTCB->pNext == pObj->pTCBList)
    {
        pObj->pTCBList = NULL;
    }
    else
    {
        while (pTCB->pNext != pObj->pTCBList)
        {
            if (pTCB->pNext == pCurTCB)
            {
                break;
            }

            pTCB = pTCB->pNext;
        }

        pTCB->pNext = pCurTCB->pNext;

        if (pCurTCB == pObj->pTCBList)
        {
            pObj->pTCBList = pCurTCB->pNext;
        }
    }
}

static uint8_t GetTaskNum(OsInfo_t *pObj)
{
    uint8_t num = 0;
    TCB_t *pTCB = sg_OsInfo.pTCBList;

    if (pTCB == NULL)
    {
        return 0;
    }

    do {
        if (pTCB->state != TASK_STATUS_DELETED)
        {
            num++;
        }

        pTCB = pTCB->pNext;
    } while (pTCB != sg_OsInfo.pTCBList);

    return num;
}

/**
  * @brief      初始化协程OS系统
  * 
  * @attention  回调函数不可为NULL
  * @param      pfOsTimer 获取毫秒级别的时间回调函数
  */
void cotOs_Init(cotOsGetSysTime_f pfnOsTimer)
{
    sg_OsInfo.pfnGetTimerMs = pfnOsTimer;
    sg_OsInfo.pTCBList = NULL;
    sg_OsInfo.pCurTCB = NULL;
#if COT_OS_MAX_SHARED_TASK > 0
    sg_OsInfo.tcbStackMask = 0;
#endif
    sg_OsInfo.tcbMask = 0;
    sg_OsInfo.pidCount = 0;
    sg_OsInfo.pfnRunTask = RunTask;
    sg_OsInfo.pfnGetStackTop = GetStackTop;
    sg_OsInfo.pfnCalculateStackUsage = CalculateStackUsage;
}

static void DestoryTask(OsInfo_t *pObj, TCB_t *pCurTCB)
{
    if (pCurTCB->state == TASK_STATUS_DELETED && pCurTCB->joinWaitCnt == 0)
    {
#if COT_OS_MAX_SHARED_TASK > 0
        DestroyTCBStack(&sg_OsInfo, pCurTCB);
#endif
        DeleteFromTCBTaskList(&sg_OsInfo, pCurTCB);
        DestroyTCB(&sg_OsInfo, pCurTCB);
    }
}

static void RunTask(uint32_t check)
{
    COT_OS_ENABLE_IRQ();
    sg_OsInfo.pCurTCB->state = TASK_STATUS_RUNNING;
    sg_OsInfo.pCurTCB->pfnOsTaskEnter(sg_OsInfo.pCurTCB->param);
    while(check != TCB_MAGIC);// 程序卡在这则说明该任务的栈可能被破坏了
    sg_OsInfo.pCurTCB->state = TASK_STATUS_DELETED;
    cotOs_ConditionNotify(&sg_OsInfo.pCurTCB->cond);
    DestoryTask(&sg_OsInfo, sg_OsInfo.pCurTCB);

    if (GetTaskNum(&sg_OsInfo) > 0)
    {
        JumpNextTask(&sg_OsInfo);
    }
    else
    {
        longjmp(sg_OsInfo.env, MAIN_TASK_EXIT);
    }
}

static bool CheckStackMem(OsInfo_t *pObj, void *pStack, size_t stackSize)
{
    if (pObj->pTCBList != NULL)
    {
        TCB_t *pTCB = pObj->pTCBList;

        size_t newStackTop = (size_t)pStack + stackSize;
        size_t newStackBase = (size_t)pStack;

        do {
            size_t stackTop = (size_t)pTCB->stackTop;
            size_t stackBase = (size_t)pTCB->stackTop - pTCB->stackSize;

            if (!(newStackTop <= stackBase || newStackBase >= stackTop))
            {
                return false;
            }

            pTCB = pTCB->pNext;
        } while (pTCB != pObj->pTCBList);
    }

    return true;
}

/**
  * @brief      创建独立栈任务
  * 
  * @param      pfnOsTaskEnter 任务入口函数
  * @param      pName          任务名字
  * @param      pStack         栈空间，选择共享栈是该值为NULL
  * @param      stackSize      栈空间大小，选择共享栈是该值为0
  * @param      arg            任务入口函数参数
  * @return     任务ID，小于0则失败
  */
cotOsTask_t cotOs_CreatTaskWithStack(cotOsTask_f pfnOsTaskEnter, const char *pName, void *pStack, size_t stackSize, int arg)
{
    TCB_t *pNewTCB = NULL;

    if (sg_OsInfo.pfnGetTimerMs == NULL)
    {
        return COT_ERROR_NOT_INIT;
    }

    if (pStack == NULL || stackSize == 0)
    {
        return COT_ERROR_STACK_IS_NULL;
    }

    if (!CheckStackMem(&sg_OsInfo, pStack, stackSize))
    {
        return COT_ERROR_STACK_OVERLAPPING;
    }

    pNewTCB = CreatTCB(&sg_OsInfo);

    if (NULL == pNewTCB)
    {
        return COT_ERROR_TCB_MEM_FAIL;
    }

    MaxStrpy(pNewTCB->szName, pName, sizeof(pNewTCB->szName));
    pNewTCB->pid = sg_OsInfo.pidCount++;
    pNewTCB->pfnOsTaskEnter = pfnOsTaskEnter;
    pNewTCB->param = arg;
    pNewTCB->stackTop = (size_t)pStack + stackSize;
    pNewTCB->stackSize = stackSize;
    pNewTCB->eStackType = COT_OS_UNIQUE_STACK;
    pNewTCB->pNext = NULL;
    pNewTCB->state = TASK_STATUS_INIT;
    pNewTCB->pCondition = NULL;
#if COT_OS_MAX_SHARED_TASK > 0
    pNewTCB->pBakStack = NULL;
#endif
    pNewTCB->nextRunTime = 0;
    pNewTCB->joinWaitCnt = 0;
    cotOs_ConditionInit(&pNewTCB->cond);
    AddToTCBTaskList(&sg_OsInfo, pNewTCB);

    return pNewTCB->pid;
}

/**
  * @brief      创建共享栈任务
  * 
  * @attention  使用`cotOs_Wait`和`cotOs_ConditionWait`仅限于在任务入口函数中使用，禁止在任务函数中的嵌套函数中使用
  * @attention  不建议在任务入口函数中定义过多变量或者大内存变量，嵌套函数没有要求
  * @note       启动任务后会利用剩余的栈空间完成共享栈的使用
  * @param      pfnOsTaskEnter 任务入口函数
  * @param      pName          任务名字
  * @param      arg            任务入口函数参数
  * @return     任务ID，小于0则失败
  */
cotOsTask_t cotOs_CreatTask(cotOsTask_f pfnOsTaskEnter, const char *pName, int arg)
{
    TCB_t *pNewTCB = NULL;

    if (sg_OsInfo.pfnGetTimerMs == NULL)
    {
        return COT_ERROR_NOT_INIT;
    }

    pNewTCB = CreatTCB(&sg_OsInfo);

    if (NULL == pNewTCB)
    {
        return COT_ERROR_TCB_MEM_FAIL;
    }

    MaxStrpy(pNewTCB->szName, pName, sizeof(pNewTCB->szName));
    pNewTCB->pid = sg_OsInfo.pidCount++;
    pNewTCB->pfnOsTaskEnter = pfnOsTaskEnter;
    pNewTCB->param = arg;
    pNewTCB->stackTop = 0;
    pNewTCB->eStackType = COT_OS_SHARED_STACK;
    pNewTCB->pNext = NULL;
    pNewTCB->state = TASK_STATUS_INIT;
    pNewTCB->pCondition = NULL;
#if COT_OS_MAX_SHARED_TASK > 0
    pNewTCB->pBakStack = CreatTCBStack(&sg_OsInfo);

    if (pNewTCB->pBakStack == NULL)
    {
        DestroyTCB(&sg_OsInfo, sg_OsInfo.pCurTCB);
        return COT_ERROR_TCB_MEM_STACK_FAIL;
    }
#endif
    pNewTCB->nextRunTime = 0;
    pNewTCB->joinWaitCnt = 0;
    cotOs_ConditionInit(&pNewTCB->cond);

    AddToTCBTaskList(&sg_OsInfo, pNewTCB);

    return pNewTCB->pid;
}

#if COT_OS_MAX_SHARED_TASK > 0
static void StartSharedTask(void)
{
    volatile char resBuf[COT_OS_SHARED_TASK_JMP_STACK_SIZE];
    UseBuffer(resBuf);

    sg_OsInfo.pCurTCB->stackTop = sg_OsInfo.pfnGetStackTop();

    if (COMMON_TASK_INTI == setjmp(sg_OsInfo.pCurTCB->env))
    {
        sg_OsInfo.pfnRunTask(TCB_MAGIC);
    }
}

static void UseBuffer(volatile char* buf)
{
    // 进行一些操作, 防止编译优化
    buf[0] = 0;
}
#endif
/**
  * @brief      启动协程OS任务
  * 
  * @attention  存在任务函数时该函数不会退出, 因此一切准备就绪后最后调用该函数即可
  * @return     0,成功; -1,失败
  */
int cotOs_Start(void)
{
    if (sg_OsInfo.pTCBList == NULL || sg_OsInfo.pfnGetTimerMs == NULL)
    {
        return -1;
    }

    int ret = setjmp(sg_OsInfo.env);

    if (MAIN_TASK_INTI == ret)
    {
        sg_OsInfo.pCurTCB = sg_OsInfo.pTCBList;
        longjmp(sg_OsInfo.env, MAIN_TASK_START_TASK);
    }
    else if (MAIN_TASK_START_TASK == ret)
    {
        if (sg_OsInfo.pCurTCB->eStackType == COT_OS_UNIQUE_STACK)
        {
#if (COT_OS_MAX_UNIQUE_TASK > 0)
            COT_OS_SET_STACK(sg_OsInfo.pCurTCB->stackTop);
            sg_OsInfo.pfnRunTask(TCB_MAGIC);
#endif
        }
        else
        {
#if (COT_OS_MAX_SHARED_TASK > 0)
            StartSharedTask();
#endif
        }
    }
#if COT_OS_MAX_SHARED_TASK > 0
    else if (MAIN_TASK_JUMP_SHARED_TASK == ret)
    {
        RestoreSharedStack(sg_OsInfo.pCurTCB);
        longjmp(sg_OsInfo.pCurTCB->env, COMMON_TASK_RUN);
    }
#endif
    return 0;
}

static void JumpNextTask(OsInfo_t *pObj)
{
    if (pObj->pTCBList != NULL)
    {
        while (1)
        {
            TCB_t *pTCB = pObj->pTCBList;

            do {
                if (pTCB->state != TASK_STATUS_DELETED && pTCB->state != TASK_STATUS_INIT)
                {
                    if (((pTCB->nextRunTime != 0 && pObj->pfnGetTimerMs() > pTCB->nextRunTime) || 
                        (pTCB->pCondition != NULL && pTCB->pCondition->flag == 1)))
                    {
                        pTCB->state = TASK_STATUS_READY;
                    }
                }

                pTCB = pTCB->pNext;
            } while (pTCB != pObj->pTCBList);

            do {
                if (pTCB->state == TASK_STATUS_READY && pTCB->pCondition != NULL)
                    pTCB->pCondition->flag = 0;

                pTCB = pTCB->pNext;
            } while (pTCB != pObj->pTCBList);

            pTCB = pObj->pCurTCB->pNext;

            do {
                if (pTCB->state == TASK_STATUS_READY)
                {
                    pObj->pCurTCB = pTCB;
                    pObj->pCurTCB->state = TASK_STATUS_RUNNING;
#if COT_OS_MAX_SHARED_TASK > 0
                    if (pObj->pCurTCB->pBakStack != NULL)
                    {
                        COT_OS_DISABLE_IRQ();
                        longjmp(sg_OsInfo.env, MAIN_TASK_JUMP_SHARED_TASK);
                    }
                    else
#endif
                    {
                        longjmp(pObj->pCurTCB->env, COMMON_TASK_RUN);
                    }
                }
                else if (pTCB->state == TASK_STATUS_INIT)
                {
                    sg_OsInfo.pCurTCB = pTCB;
                    COT_OS_DISABLE_IRQ();
                    longjmp(sg_OsInfo.env, MAIN_TASK_START_TASK);
                }

                pTCB = pTCB->pNext;
            } while (pTCB != pObj->pCurTCB->pNext);
        }
    }
}

/**
  * @brief      任务阻塞等待时间结束
  * 
  * @note       等待n毫秒时长, 则会在 >= n 后的某个时刻才会运行, 具体要看其他协程任务什么时候让出资源
  * @param      time 等待时长，单位毫秒
  */
void cotOs_Wait(uint32_t time)
{
    sg_OsInfo.pCurTCB->nextRunTime = sg_OsInfo.pfnGetTimerMs() + time;
    sg_OsInfo.pCurTCB->pCondition = NULL;
    sg_OsInfo.pCurTCB->state = TASK_STATUS_SUSPEND;

    if (COMMON_TASK_RUN != setjmp(sg_OsInfo.pCurTCB->env))
    {
#if COT_OS_MAX_SHARED_TASK > 0
        if (sg_OsInfo.pCurTCB->pBakStack != NULL)
        {
            BackupSharedStack(sg_OsInfo.pCurTCB);
        }
#endif
        JumpNextTask(&sg_OsInfo);
    }

    COT_OS_ENABLE_IRQ();
}

/**
  * @brief      等待任务退出
  * 
  * @param      task cotOs_CreatTask 或 cotOs_CreatTaskWithStack 返回的值
  */
void cotOs_Join(cotOsTask_t task)
{
    TCB_t *pTCB = sg_OsInfo.pTCBList;

    do {
        if (pTCB->pid == task && pTCB->state != TASK_STATUS_DELETED)
        {
            pTCB->joinWaitCnt++;
            cotOs_ConditionWait(&pTCB->cond);
            pTCB->joinWaitCnt--;
            DestoryTask(&sg_OsInfo, pTCB);
            break;
        }

        pTCB = pTCB->pNext;
    } while (pTCB != sg_OsInfo.pTCBList);
}

/**
  * @brief      获取当前任务的ID
  * 
  * @return     uint16_t 
  */
uint16_t cotOs_Pid(void)
{
    return sg_OsInfo.pCurTCB->pid;
}

/**
  * @brief      条件事件初始化
  * 
  * @param      pCondition 条件事件
  */
void cotOs_ConditionInit(CotOSCondition_t *pCondition)
{
    if (pCondition == NULL)
    {
        return;
    }

    pCondition->flag = 0;
}

/**
  * @brief      任务阻塞等待条件事件发生
  * 
  * @note       等待条件事件发生, 则会在条件事件发生后的某个时刻才会运行, 具体要看其他协程任务什么时候让出资源
  * @param      pCondition 条件事件
  */
void cotOs_ConditionWait(CotOSCondition_t *pCondition)
{
    if (pCondition == NULL)
    {
        return;
    }

    sg_OsInfo.pCurTCB->nextRunTime = 0;
    sg_OsInfo.pCurTCB->pCondition = pCondition;
    sg_OsInfo.pCurTCB->state = TASK_STATUS_SUSPEND;

    if (COMMON_TASK_RUN != setjmp(sg_OsInfo.pCurTCB->env))
    {
#if COT_OS_MAX_SHARED_TASK > 0
        if (sg_OsInfo.pCurTCB->pBakStack != NULL)
        {
            BackupSharedStack(sg_OsInfo.pCurTCB);
        }
#endif
        JumpNextTask(&sg_OsInfo);
    }

    COT_OS_ENABLE_IRQ();
}

/**
  * @brief      触发条件事件
  * 
  * @param      pCondition 条件事件
  */
void cotOs_ConditionNotify(CotOSCondition_t *pCondition)
{
    if (pCondition == NULL)
    {
        return;
    }

    pCondition->flag = 1;
}

#if 0
#include <stdio.h>

#define GET_STATUS(state)  (state) == TASK_STATUS_READY ? "R" : \
    ((state) == TASK_STATUS_RUNNING ? "X" : \
    ((state) == TASK_STATUS_SUSPEND ? "S" : "D"))

void cotOs_Top(void)
{
    printf("%3s  %-16s %-6s %-8s\n", "pid", "name", "state", "stack");

    for (int i = 0; i < COT_OS_MAX_TASK; i++)
    {
        if (((sg_OsInfo.tcbMask >> i) & 0x01))
        {
            printf("%3d  %-16s %-6s %-8lx\n", sg_TCB[i].pid, sg_TCB[i].szName, GET_STATUS(sg_TCB[i].state), sg_TCB[i].stackTop);
        }
    }
}
#endif
